package org.liang.common.utils.codec;

import java.security.SecureRandom;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.spec.SecretKeySpec;

import org.apache.commons.codec.binary.Base64;


/**
 * 加密解密工具.
 * 
 * <pre>
 * 1. 加密
 *   先进行aes 加密，然后再对aes加密后的内容进行base64加密
 * 2. 解密
 *   先进行base64解密，然后在对base64解密后的内容进行aes解密
 * </pre>
 * 
 * @author L.Yang
 * @version 1.0, 2015年9月6日
 */
public class PasswordCodec {

    private static final String CHARSET = "UTF-8";

    /** 默认密钥 . */
    public static final String DEF_KEY = "liang.[olddriver]";

    /**
     * 对指定字符串进行加密.
     * 
     * <pre>
     * 先进行aes 加密，然后再对aes加密后的内容进行base64加密
     * </pre>
     * 
     * @param content
     *            原文
     * @param key
     *            密钥
     * @return 密文
     */
    public static String encrypt(String content, String key) throws Exception {
        return new String(Base64.encodeBase64(aes(content.getBytes(CHARSET), key,
                        Cipher.ENCRYPT_MODE)));
    }

    /**
     * 对指定字符用进行解密操作，与加密操作对.
     * 
     * <pre>
     * 先对传入内容进行base64解密，然后进行aes解密
     * </pre>
     * 
     * @param content
     *            密文
     * @param key
     *            密钥
     * @return 明文
     */
    public static String decrypt(String content, String key) throws Exception {
        return new String(aes(Base64.decodeBase64(content), key, Cipher.DECRYPT_MODE), CHARSET);
    }

    /**
     * AES加密解密.
     * 
     * @param byteData
     *            要处理的数据
     * @param key
     *            秘钥
     * @param opmode
     *            加密/解密
     * @return 处理后的字符
     */
    private static byte[] aes(byte[] byteData, String key, int opmode) throws Exception {
        KeyGenerator kgen = KeyGenerator.getInstance("AES");
        kgen.init(128, new SecureRandom(key.getBytes("UTF-8")));
        Cipher cipher = Cipher.getInstance("AES");
        cipher.init(opmode, new SecretKeySpec(kgen.generateKey().getEncoded(), "AES"));
        return cipher.doFinal(byteData);
    }
}
